//
//  PullDownRefreshControl.swift
//  Weibo
//
//  Created by lzing on 16/3/29.
//  Copyright © 2016年 lzing. All rights reserved.
//

import UIKit

//MARK: - 动态添加属性
private var pullDownRefreshControlKey = "pullDownRefreshControlKey"
extension UIScrollView {
    // 使用运行时动态关联控件
    var pullDownRefreshControl: PullDownRefreshControl {
        get {
            // 根据key的值取出对象
            if let refreshControl = objc_getAssociatedObject(self, &pullDownRefreshControlKey) as? PullDownRefreshControl {
                return refreshControl
            } else  {
                //在对象身上没有找到需要东西
                let refreshControl = PullDownRefreshControl()
                // 添加到scrollView上
                self.addSubview(refreshControl)
                // 关联到self
                self.pullDownRefreshControl = refreshControl
                
                return refreshControl
            }
        }
        
        set {
            objc_setAssociatedObject(self, &pullDownRefreshControlKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    // MARK: - 添加3个对外公开的方法,不让外部直接访问下拉刷新控件属性
    ///  释放刷新的闭包
    func addPullDownRefreshHandler(handle:() -> ()) {
        pullDownRefreshControl.pulldownRefreshHandler = handle
    }
    
    ///  开始刷新
    func startRefreshing() {
        pullDownRefreshControl.startRefreshing()
    }
    
    ///  结束刷新
    func endRefreshing() {
        pullDownRefreshControl.endRefreshing()
    }
}

/// 刷新控件高度
private let PulldownRefreshControlHeight : CGFloat = 60

///  定义枚举
enum PulldownRefreshControlStatus : Int {
    case Normal /// 普通状态, 下拉刷新
    case PullToRefresh /// 拖动状态, 释放刷新
    case Refreshing /// 正在刷新
}

class PullDownRefreshControl: UIView {
    //MARK: - 属性
    ///  刷新控件回调
    var pulldownRefreshHandler : (() -> ())?
    // 记录属性
    private weak var scrollView : UIScrollView!
    // 记录上一次状态
    private var oldStatus : PulldownRefreshControlStatus = .Normal
    // 刷新控件的当前状态, 默认是normal
    private var currentStatus : PulldownRefreshControlStatus = .Normal {
        didSet {
            // 状态改变后来改变UI
            switch currentStatus {
            case .Normal :
                // 箭头转下来,文字变为: 下拉刷新
                // 移除风火轮的旋转动画
                circleView.layer.removeAllAnimations()
                arrowView.hidden = false
                circleView.hidden = true
                messageLabel.text = "下拉刷新"
                // 开启动画进行旋转
                UIView.animateWithDuration(LZDefaultDuration, animations: { () -> Void in
                    self.arrowView.transform = CGAffineTransformIdentity
                })
                // 状态只有刷新的时候,再切换到Normal的时候,才让tableView往上移动一个刷新控件高度,把刷新控件隐藏
                if oldStatus == .Refreshing {
                    UIView.animateWithDuration(LZDefaultDuration, animations: { () -> Void in
                        self.scrollView.contentInset.top -= PulldownRefreshControlHeight
                    })
                }
                
            case .PullToRefresh :
                // 箭头翻转, 文字变为刷新控件
                messageLabel.text = "释放刷新"
                UIView.animateWithDuration(LZDefaultDuration, animations: { () -> Void in
                    self.arrowView.transform = CGAffineTransformMakeRotation(CGFloat(M_PI))
                })
                
            case .Refreshing :
                // 箭头隐藏,文字变为: 正在刷新
                arrowView.hidden = true
                circleView.hidden = false
                messageLabel.text = "正在刷新..."
                ///  开启基本动画
                let rotation = CABasicAnimation(keyPath: "transform.rotation")
                rotation.toValue = M_PI * 2
                rotation.duration = 0.5
                rotation.repeatCount = MAXFLOAT
                // 增加动画
                circleView.layer.addAnimation(rotation, forKey: "rotation")
                // 修改scrollView.contentInset.top,让tableView不要滚动到原来的位置,需要在往下移动刷新控件的高度,就能显示刷新控件
                UIView.animateWithDuration(LZDefaultDuration, animations: { () -> Void in
                    self.scrollView.contentInset.top += PulldownRefreshControlHeight
                    }, completion: { (_) -> Void in
                        // 刷新控件动画到导航栏下面的时候调用
                        self.pulldownRefreshHandler?()
                })
            }
            // 赋值当前状态
            oldStatus = currentStatus
        }
    }
    
    //MARK: - 公开方法
    // 开始刷新
    func startRefreshing() {
        currentStatus = .Refreshing
    }
    // 结束刷新时调用
    func endRefreshing() {
        currentStatus = .Normal
    }
    
    // 移除KVO
    deinit {
        scrollView.removeObserver(self, forKeyPath: "contentOffset")
    }
    
    // 设置控件默认大小
    override init(frame: CGRect) {
        let newFrame = CGRect(x: 0, y: -PulldownRefreshControlHeight, width: UIScreen.width, height: PulldownRefreshControlHeight)
        super.init(frame: newFrame)
        backgroundColor = UIColor.clearColor()
        // 添加子控件
        addSubview()
        // 添加子控件约束
        addConstraint()
        // 隐藏转动view
        circleView.hidden = true
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    // MARK: - 添加子控件
    @objc private func addSubview() {
        addSubview(arrowView)
        addSubview(circleView)
        addSubview(messageLabel)
    }
    
    // MARK: - 添加约束
    @objc private func addConstraint() {
        // 关闭autoresizing
        arrowView.translatesAutoresizingMaskIntoConstraints = false
        circleView.translatesAutoresizingMaskIntoConstraints = false
        messageLabel.translatesAutoresizingMaskIntoConstraints = false
        // 箭头
        addConstraint(NSLayoutConstraint(item: arrowView, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: self, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: -30))
        addConstraint(NSLayoutConstraint(item: arrowView, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: self, attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant: 0))
        
        // 风火轮
        addConstraint(NSLayoutConstraint(item: circleView, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: arrowView, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: 0))
        addConstraint(NSLayoutConstraint(item: circleView, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: arrowView, attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant: 0))
        
        // messageLabel
        addConstraint(NSLayoutConstraint(item: messageLabel, attribute: NSLayoutAttribute.Left, relatedBy: NSLayoutRelation.Equal, toItem: arrowView, attribute: NSLayoutAttribute.Right, multiplier: 1, constant: 10))
        addConstraint(NSLayoutConstraint(item: messageLabel, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: arrowView, attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant: 0))
    }
    
    // 当调用addsubview
    override func willMoveToSuperview(newSuperview: UIView?) {
        super.willMoveToSuperview(newSuperview)
        // KVO,监听父类对象属性的改变tableView.contentOffset
        if let scrollView = newSuperview as? UIScrollView {
            self.scrollView = scrollView
            ///  scrollView, 监听对象
            ///  observer, 谁来监听
            ///  keyPath, 监听属性
            ///  options, New, old
            ///  context, 上下文
            scrollView.addObserver(self, forKeyPath: "contentOffset", options: [NSKeyValueObservingOptions.New, NSKeyValueObservingOptions.Old], context: nil)
        }
    }
    
    ///  KVO,当监听对象属性发生改变的时候回调用
    override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
        // scrollView是否拖动
        if scrollView.dragging {
            // scrollView正在手指推动状态
            if currentStatus == .PullToRefresh && scrollView.contentOffset.y > -scrollView.contentInset.top - PulldownRefreshControlHeight {
                // 切换到normal
//                LZPrint(msg: "切换到Normal")
                currentStatus = .Normal
            } else if currentStatus == .Normal && scrollView.contentOffset.y < -scrollView.contentInset.top - PulldownRefreshControlHeight {
                // 切换到PullToRefresh
//                LZPrint(msg: "切换到PullToRefresh")
                currentStatus = .PullToRefresh
            }
        } else if currentStatus == .PullToRefresh {
            // 手指松开切换到Refreshing
//            LZPrint(msg: "切换到Refreshing")
            currentStatus = .Refreshing
        }
    }
    
    // MARK: - lazy
    ///  箭头
    private lazy var arrowView : UIImageView = UIImageView(image: UIImage(named: "tableview_pull_refresh"))
    ///  circle
    private lazy var circleView : UIImageView = UIImageView(image: UIImage(named: "tableview_loading"))
    ///  显示信息
    private lazy var messageLabel : UILabel = {
        let messageLabel = UILabel()
        // 设置文本属性
        messageLabel.textColor = UIColor.darkGrayColor()
        messageLabel.font = UIFont.systemFontOfSize(14)
        messageLabel.text = "下拉刷新"
        return messageLabel
    }()
}
